import { add, divide, multiply, subtract, toFixeds } from "./bigNumber";
import print from "./print";
import { ASTNode } from "./types";

export const evaluate = (node: ASTNode): string => {
  print.info("evaluate.node:", node);
  switch (node.type) {
    case "NUMBER":
      return node.value as string;

    case "BINARY": {
      const left = evaluate(node.left as ASTNode);
      const right = evaluate(node.right as ASTNode);
      print.info("node.operator:", node.operator);
      print.info("evaluate:_left:", left);
      print.info("evaluate:_right:", right);
      switch (node.operator) {
        case "+":
          return add(left, right);
        case "-":
          return subtract(left, right);
        case "*":
          return multiply(left, right);
        case "/":
          return divide(left, right);
        //   return pow(left, Number(toString(right)));
        case ",":
          return "";
        default:
          throw new Error("Unknown operator");
      }
    }

    case "FUNCTION": {
      const args = node.args?.map((arg) => evaluate(arg)) || [];
      // 逗号后数值
      const numArgs = node.numArgs?.map((arg) => evaluate(arg)) || [];
      print.info("FUNCTION:", args);
      print.info("逗号后数值：", numArgs);
      let prefix = "";
      if (args[0]?.startsWith("-")) {
        prefix = "-";
        print.info("FUNCTION_prefix:", prefix);
      }

      switch (node.name) {
        case "sqrt":
        // return `${Math.sqrt()}`;
        case "pow":
          return `${Math.pow(Number(args[0]), Number(numArgs?.[0] || 1))}`;
        case "floor":
          // 负数-1
          return prefix
            ? `${subtract(args[0]?.split(".")[0]?.replace(/^-/, ""), "1")}`
            : args[0]?.split(".")[0];
        case "ceil":
          return prefix
            ? args[0]?.split(".")[0]
            : `${add(args[0]?.split(".")[0]?.replace(/^-/, ""), "1")}`;
        case "tofixeds":
          return toFixeds(args[0], Number(numArgs?.[0] || 2));
        default:
          throw new Error(`Unsupported function: ${node.name}`);
      }
    }
    case "NUMARG": {
      return "";
    }

    default:
      throw new Error("Unknown node type");
  }
};
